﻿using System;
using System.Collections.Generic;
using System.Linq;
using GameObjects;
using ServerObjects;

namespace WcfService1
{
    // NOTE: If you change the class name "Service1" here, you must also update the reference to "Service1" in Web.config and in the associated .svc file.
    public class Service1 : IService1
    {
        private readonly GameServer gameServer;

        public Service1()
        {
            gameServer = new GameServer();
        }

        public DateTime GetServerTime()
        {
            return DateTime.Now;
        } 

        //public byte[] GetGameState(int game, int turn)
        //{
        //    return gameServer.GetCompressedGameState(game, turn);
        //}

        public byte[] GetInitialGameState(int game)
        {
            return CompressHelper.Compress(Utils.SerialiseHelper.SerializeToBase64(gameServer.GetGameState(game)));
        }


        public int GetCurrentGameTurn(int gameId)
        {
            return gameServer.GetCurrentGameTurn(gameId).Turn;
        }
        
        public List<TurnOrdersDto> GetAllOrders(int gameId)
        {
            var gameTurn = gameServer.GetCurrentGameTurn(gameId);

            var turnOrders = new List<TurnOrdersDto>();

            for (var i = 0; i < gameTurn.Turn; i++)
            {
                turnOrders.Add(new TurnOrdersDto(i, gameServer.GetOrders(gameId, i)));
            }
            return turnOrders;
        }

        public List<UnitOrderDto> GetOrders(int gameId, int turn)
        {
            return gameServer.GetOrders(gameId, turn);
        }

        public GameDto GetGame(int gameId)
        {
            var game = gameServer.GetGames(true).SingleOrDefault(o => o.Id == gameId);

            return game == null ? null : GetGameDto(game);
        }

        public List<GameDto> GetGames()
        {
            var games = gameServer.GetGames(false);

            var gameDtos = new List<GameDto>();
            foreach (var game in games)
            {
                gameDtos.Add(GetGameDto(game));
            }
            return gameDtos;
        }

        private GameDto GetGameDto(Game game)
        {
            var gameTurn = gameServer.GetCurrentGameTurn(game.Id);
            return gameTurn != null ? new GameDto(game.Id, game.Name, gameTurn.Turn, game.TurnLimit, gameTurn.TurnEnds, GetFactionDtos(gameServer.GetFactions(game.Id))) : null;
        }

        static List<FactionDto> GetFactionDtos(IEnumerable<Faction> factions)
        {
            if (factions == null)
                return null;

            var fDtos = new List<FactionDto>();
            foreach (var f in factions)
                fDtos.Add(new FactionDto(f.Id, f.Name));
            return fDtos;
        }

        //private List<FactionDto> getfactions(int gameid)
        //{
        //    return GetGactionDtos(gameserver.getfactions(gameid));
        //}

        public bool ReceiveOrders(int gameId, int turn, int factionId, List<UnitOrderDto> dtoOrders)
        {
            //var gt = gameServer.GetCurrentGameTurn(gameId);

            //if (gt == null)
            //    return false;

            //// If it isn't the current game turn, assume that the orders are already in.
            //if (gt.Turn != turn)
            //    return true;

            //var orders = (List<UnitOrderDto>)Utils.SerialiseHelper.DeserializeToObject(CompressHelper.Decompress(gameServer.GetOrders(gameId, turn)));

            //orders.AddRange(dtoOrders);

            //var faction = gameState.Factions.Single(o => o.Id == factionId);

            //foreach (var dtoOrder in dtoOrders)
            //{
            //    var unitOrder = new UnitOrder(gameState.Units.Single(o => o.Id == dtoOrder.UnitId));

            //    for (var i = 0; i < dtoOrder.Hexes.Count; i++)
            //        unitOrder.Hexes.Add(gameState.Board.Hexes.Single(o => o.Id == dtoOrder.Hexes[i]));

            //    faction.Orders.Add(unitOrder);
            //}
            //faction.OrdersIn = true;

            //gameServer.GetOrders()

            return gameServer.SaveOrders(gameId, turn, factionId, dtoOrders);
        }

        public bool DeleteOrder(int gameId, int turn, int unitId)
        {
            return gameServer.DeleteOrder(gameId, turn, unitId);
        }

        public bool ReceiveOrder(int gameId, int turn, int factionId, UnitOrderDto order)
        {
            return gameServer.SaveOrders(gameId, turn, factionId, new List<UnitOrderDto> { order });
        }

        public List<MapDto> GetMaps()
        {
            var maps = gameServer.GetMaps();
            var mapDtos = new List<MapDto>();
            foreach (var m in maps)
                mapDtos.Add(new MapDto(m.Id, m.Name));

            return mapDtos;
        }

        public int CreateGame(int mapId, string gameName, int turnLimit, TimeSpan turnTimeLimit)
        {
            return gameServer.CreateGame(mapId, gameName, turnLimit, turnTimeLimit);
        }

        public void EndTurn(int gameId, int turn)
        {
            gameServer.EndTurn(gameId, turn);
        }

        public void EndGame(int gameId)
        {
            gameServer.EndGame(gameId);
        }
    }
}
